package com.swa.freemusic.util.shared4;

import java.util.Hashtable;
import java.util.Vector;

import org.ksoap2.SoapEnvelope;
import org.ksoap2.serialization.PropertyInfo;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.Transport;
import org.ksoap2.transport.AndroidHttpTransport;

/**
 * 4shared API local layer
 */
public class ForSharedService {
	private String mUsername;
	private String mPassword;
	private static final String SERVICE_URL = "http://api.4shared.com/jax2/DesktopApp";
	private static final String SERVICE_NAMESPACE = "http://api.soap.shared.pmstation.com/";

	/**
	 * Constructs this object for an account
	 * 
	 * @param username
	 *            Username of the account
	 * @param password
	 *            Password of the account
	 */
	public ForSharedService(String username, String password) {
		mUsername = username;
		mPassword = password;
	}

	/**
	 * Login with current account
	 */
	public void login() throws Exception {
		String methodName = "login";
		SoapObject rpc = getRpc(methodName);
		SoapSerializationEnvelope envelope = getEnvelope(rpc);
		Transport ht = getHttpTransport();

		String result;

		ht.call(SERVICE_URL + "/" + methodName, envelope);
		result = (envelope.getResponse()).toString();

		if (!isEmptyString(result))
			throw new Exception(result);
	}

	/**
	 * Get account's root folder
	 * 
	 * @return Item representing the root directory
	 */
	public AccountItem getRoot() throws Exception {
		String soapAction = SERVICE_URL + "/getRoot";

		SoapObject rpc = getRpc("getRoot");
		SoapSerializationEnvelope envelope = getEnvelope(rpc);
		Transport ht = getHttpTransport();

		ht.call(soapAction, envelope);
		return getAccountItem((SoapObject) envelope.getResponse());
	}

	/**
	 * Get contents of a directory
	 * 
	 * @param dirId
	 *            Directory's identifier
	 * @return Array of items representing contents of the directory
	 */
	public AccountItem[] getItems(long dirId) throws Exception {
		String methodName = "getItems";

		SoapObject rpc = getRpc(methodName);
		rpc.addProperty("arg2", new Long(dirId));
		SoapSerializationEnvelope envelope = getEnvelope(rpc);

		Transport ht = getHttpTransport();

		ht.call(SERVICE_URL + "/" + methodName, envelope);
		Object result = envelope.getResponse();

		return getAccountItems(result);
	}

	public AccountItem[] getAllItems() throws Exception {
		String methodName = "getAllItems";

		SoapObject rpc = getRpc(methodName);
		SoapSerializationEnvelope envelope = getEnvelope(rpc);

		Transport ht = getHttpTransport();

		ht.call(SERVICE_URL + "/" + methodName, envelope);
		Object result = envelope.getResponse();

		return getAccountItems(result);
	}

	public String getFileDownloadLink(long fileID) throws Exception {
		String methodName = "getFileDownloadLink";

		SoapObject rpc = getRpc(methodName);
		rpc.addProperty("arg2", new Long(fileID));
		SoapSerializationEnvelope envelope = getEnvelope(rpc);

		Transport ht = getHttpTransport();

		ht.call(SERVICE_URL + "/" + methodName, envelope);
		Object result = envelope.getResponse();

		return result.toString();
	}

	public String getDirectLink(String link) throws Exception {
		String methodName = "getDirectLink";

		SoapObject rpc = getRpc(methodName);
		rpc.addProperty("arg2", link);
		SoapSerializationEnvelope envelope = getEnvelope(rpc);

		Transport ht = getHttpTransport();

		ht.call(SERVICE_URL + "/" + methodName, envelope);
		Object result = envelope.getResponse();

		return result.toString();
	}

	private Transport getHttpTransport() {
		Transport ht = new AndroidHttpTransport(SERVICE_URL);
		ht.setXmlVersionTag("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
		ht.debug = true;

		return ht;
	}

	private SoapObject getRpc(String methodName) {
		SoapObject rpc = new SoapObject(SERVICE_NAMESPACE, methodName);
		rpc.addProperty("arg0", mUsername);
		rpc.addProperty("arg1", mPassword);

		return rpc;
	}

	private SoapSerializationEnvelope getEnvelope(SoapObject rpc) {
		SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(
				SoapEnvelope.VER11);

		envelope.bodyOut = rpc;
		envelope.encodingStyle = SoapSerializationEnvelope.XSD;

		return envelope;
	}

	private AccountItem getAccountItem(SoapObject item) {
		return deserialize(new AccountItem(), item);
	}

	@SuppressWarnings("unchecked")
	private AccountItem[] getAccountItems(Object response) {
		if (response == null)
			return null;

		if (!(response instanceof SoapObject))
			return null;

		Vector items = new Vector();

		for (int i = 0; i < ((SoapObject) response).getPropertyCount(); i++) {
			Object item = ((SoapObject) response).getProperty(i);
			if (item instanceof SoapObject) {

				items.addElement(deserialize(new AccountItem(),
						(SoapObject) item));
			}
		}

		AccountItem[] accountItems = new AccountItem[items.size()];
		items.copyInto(accountItems);

		return accountItems;
	}

	@SuppressWarnings({ "unchecked", "deprecation" })
	private AccountItem deserialize(AccountItem newItem, SoapObject item) {
		Hashtable ht = new Hashtable();
		PropertyInfo propInfo = new PropertyInfo();
		for (int n = 0; n < item.getPropertyCount(); n++) {
			item.getPropertyInfo(n, ht, propInfo);
			newItem.setProperty(propInfo.name, item.getProperty(n));
		}

		return newItem;
	}

	private static boolean isEmptyString(String string) {
		return (string == null || string.equals("")
				|| string.toLowerCase().equals("string{}") || string
				.toLowerCase().equals("anytype{}"));
	}
}
